﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Threading;
using System.Xml.Serialization;
using System.IO;
using System.Windows;
using ISTKPlugin;

namespace BDSim
{
    /// <summary>
    /// 仿真场景
    /// </summary>
    [TypeConverter(typeof(PropertySorter))]
    public class Scenario : BDSimObject
    {
        public Scenario()
        {
            Name = "仿真场景";
            foreach (var item in SegmentColletion)
            {
                item.Parent = this;
            }
            GenerateInitTime();
            DlgAddCompleteMission = AddExecuteMission;
            EnvironmentSegmentList_Add();
            DataProvider.Parent = this;
            DataProvider.DefineCommand();
            Menu.ItemsSource = DataProvider.MenuCommandList;
            IsStarted = true;
            EnvironmentSegmentInit();
        }

        #region 场景属性参数

        #region 基本参数
        private ESimStatus _Status = ESimStatus.UnInited;
        private double _StepSize = 60;
        double _RunSpeed = 1;
        ERunMode _RunMode = ERunMode.END;
        PlayScenarioType _ScenarioType = PlayScenarioType.CreateNew;
        [XmlIgnore]
        public bool ObsSaveFlag = true;//用于控制loop模式不重复存储观测数据，kj
        /// <summary>
        /// 仿真场景运行模式
        /// </summary>
        [Category("基本信息"), Description("运行模式，END为结束运行，LOOP为循环运行"), PropertyOrder(5)]
        public ERunMode RunMode
        {
            get { return _RunMode; }
            set { _RunMode = value; }
        }

        /// <summary>
        /// 仿真状态
        /// </summary>
        [XmlIgnore, Category("基本信息"), Description("当前仿真状态"), ReadOnly(true), PropertyOrder(2)]
        public ESimStatus Status
        {
            get { return _Status; }
            set { _Status = value; GlobalStatus = value; NotifyPropertyChanged("Status"); }
        }

        /// <summary>
        /// 仿真步长
        /// </summary>
        [Category("基本信息"), Description("导航业务数据仿真步长"), PropertyOrder(3)]
        public double StepSize
        {
            get { return _StepSize; }
            set { _StepSize = value; GlobalStepSize = value; }
        }

        [XmlAttribute, Category("基本信息"), PropertyOrder(1)]
        public string Name
        {
            get { return _Name; }
            set
            {
                if (value != "")
                {
                    _Name = value;
                    NotifyPropertyChanged("Name");
                }
            }
        }

        /// <summary>
        /// 运行速度，即定时器步长，单位：s
        /// </summary>
        [Category("基本信息"), Description("仿真运行速度，单位：s"), PropertyOrder(4)]
        public double RunSpeed
        {
            get { return _RunSpeed; }
            set { _RunSpeed = value; NotifyPropertyChanged("RunSpeed"); }
        }

        [Browsable(true), CategoryAttribute("演示场景控制")]
        public PlayScenarioType ScenarioType
        {
            get { return _ScenarioType; }
            set { _ScenarioType = value; }
        }

        #endregion

        #region 仿真时间
        private UTCTimeClass _StartTime;
        private UTCTimeClass _EndTime;
        private UTCTimeClass _EpochTime;
        private UTCTime _CurrentTime;

        /// <summary>
        /// 仿真数据分析开始时间
        /// </summary>
        [Browsable(true), ReadOnly(true), Category("时间"), Description("数据分析开始时间"), PropertyOrder(1), TypeConverter(typeof(PropertySorter))]
        public UTCTimeClass StartTime
        {
            get { return _StartTime; }
            set
            {
                if (GlobalStatus == ESimStatus.UnInited || GlobalStatus == ESimStatus.End)
                {
                    _StartTime = value; GlobalStartTime = value.ToUTCTime();
                    NotifyPropertyChanged("StartTime");
                    //EnvironmentSegmentInit();
                }
            }
        }

        /// <summary>
        /// 仿真当前时间
        /// </summary>
        ///[Browsable(false), Category("时间"), Description("当前时间"), PropertyOrder(1), TypeConverter(typeof(PropertySorter))]
        [XmlIgnore, Description("当前时间")]
        public UTCTime CurrentTime
        {
            get { return _CurrentTime; }
            set { _CurrentTime = value; GlobalCurrentTime = value; NotifyPropertyChanged("CurrentTime"); }
        }

        /// <summary>
        /// 仿真结束时间
        /// </summary>
        [Browsable(true), ReadOnly(true), Category("时间"), Description("数据分析结束时间"), PropertyOrder(2), TypeConverter(typeof(PropertySorter))]
        public UTCTimeClass EndTime
        {
            get { return _EndTime; }
            set
            {
                if (GlobalStatus == ESimStatus.UnInited || GlobalStatus == ESimStatus.End)
                {
                    _EndTime = value; GlobalEndTime = value.ToUTCTime(); 
                    NotifyPropertyChanged("EndTime"); 
                    //EnvironmentSegmentInit();
                }
            }
        }

        /// <summary>
        /// 仿真场景开始历元
        /// </summary>
        [Browsable(true), ReadOnly(true), Category("时间"), Description("场景当前历元"), PropertyOrder(3), TypeConverter(typeof(PropertySorter))]
        public UTCTimeClass EpochTime
        {
            get { return _EpochTime; }
            set { _EpochTime = value; }
        }

        /// <summary>
        /// 当前运行到第多少步
        /// </summary>
        int _CurrentStepIndex = 0;
        [Browsable(false)]
        public int CurrentStepIndex
        {
            get { return _CurrentStepIndex; }
            set { _CurrentStepIndex = value; GlobalStepIndex = value; }
        }
        #endregion

        #region 业务控制属性
        [XmlIgnore]
        public static bool _IsFitEphemeris = true;
        [XmlIgnore]
        public static bool _IsGenerateObsData = true;
        [XmlIgnore]
        public static bool _EnableFitError = true;
        private static bool _IsPPositioning = true;
        [XmlIgnore]
        public static bool _IsTestingMode = false;

        [CategoryAttribute("业务控制"), DescriptionAttribute("观测数据仿真开关"), PropertyOrder(1), Browsable(true)]
        public bool IsGenerateObsData
        {
            get { return _IsGenerateObsData; }
            set { _IsGenerateObsData = value; }
        }

        [CategoryAttribute("业务控制"), DescriptionAttribute("星历拟合仿真开关"), PropertyOrder(2), Browsable(true)]
        public bool IsFitEphemeris
        {
            get { return _IsFitEphemeris; }
            set { _IsFitEphemeris = value; }
        }
        [CategoryAttribute("业务控制"), DescriptionAttribute("星历拟合误差项开关"), PropertyOrder(3), Browsable(true)]
        public bool EnableFitError
        {
            get { return _EnableFitError; }
            set { _EnableFitError = value; }
        }

        [CategoryAttribute("业务控制"), DescriptionAttribute("接收机定位开关"), PropertyOrder(4), Browsable(true)]
        public bool IsPPositioning
        {
            get { return Scenario._IsPPositioning; }
            set { Scenario._IsPPositioning = value; }
        }

        [CategoryAttribute("业务控制"), DescriptionAttribute("测试模式开关"), PropertyOrder(5), Browsable(true)]
        public bool IsTestingMode
        {
            get { return _IsTestingMode; }
            set { _IsTestingMode = value; }
        }

        #endregion

        #region 数据交互模型
        ScenarioDataProvider _DataProvider = new ScenarioDataProvider();

        [XmlIgnore, Browsable(false)]
        public ScenarioDataProvider DataProvider
        {
            get { return _DataProvider; }
            set { _DataProvider = value; }
        }
        #endregion

        #region 总任务量，完成任务量计数
        /// <summary>
        /// 总任务量
        /// </summary>
        double TotalMissionNum = 0;

        /// <summary>
        /// 已完成任务量
        /// </summary>
        double CompletedMissionNum = 0;

        double _PercentValue = 0;
        [XmlIgnore, Browsable(false)]
        public double PercentValue
        {
            get { return _PercentValue; }
            set { _PercentValue = value; NotifyPropertyChanged("PercentValue"); }
        }
        #endregion

        #endregion

        #region 字段
        /// <summary>
        /// 单步运行定时器
        /// </summary>
        DispatcherTimer stepRunTimer = new DispatcherTimer();        

        /// <summary>
        /// 仿真场景右键命令菜单数据源集合
        /// </summary>
        List<MenuCommand> MenuCommandList = new List<MenuCommand>();

        public bool IsStarted = false;

        /// <summary>
        /// STK插件
        /// </summary>
        [XmlIgnore]
        public static List<InterfaceSTKPlugin> stkPluginList = new List<InterfaceSTKPlugin>();

        /// <summary>
        /// STK插件加载标识
        /// </summary>
        [XmlIgnore]
        public bool STKFlag = true;

        #endregion

        #region //委托定义

        [XmlIgnore]
        public Action DlgEarthMapUpdate;
        #endregion

        #region 场景数据模型
        ObservableCollection<SegmentBase> _SegmentColletion = new ObservableCollection<SegmentBase>()
        {
            {new SpaceSegment(){Name = "空间段"}},
            {new EnvironmentSegment(){Name = "环境段"}},
            {new GroundSegment() {Name = "地面段"}},
            {new UserSegment(){Name = "用户段"}}            
        };
        [Browsable(false),XmlIgnore]
        public ObservableCollection<SegmentBase> SegmentColletion
        {
            get { return _SegmentColletion; }
            set { _SegmentColletion = value; NotifyPropertyChanged("SegmentColletion"); }
        }

        Dictionary<ESegmentType, SegmentBase> SegmentDic = new Dictionary<ESegmentType, SegmentBase>();
        #endregion 场景数据模型        

        #region 仿真运行控制
        public override void Init()
        {
            CalculateTotalMission();
            DlgReportSimInfo(SimInfo.NewSimInfo(this.Name,"正在初始化中...", OutputType.消息, CurrentTime));
            Status = ESimStatus.Initing;
            Uid = Guid.NewGuid();
            stepRunTimer.Interval = TimeSpan.FromSeconds(RunSpeed);
            stepRunTimer.Tick += new EventHandler(stepRunTimer_Tick);
            RunSpeed = 1;
            stepRunTimer.Interval = TimeSpan.FromSeconds(RunSpeed);

            GlobalStartTime = this.StartTime.ToUTCTime();
            GlobalEndTime = this.EndTime.ToUTCTime();
            CurrentTime = this.StartTime.ToUTCTime();
            TimeSpaceDll.CAL2UTC(out GlobalStartTime, 1);
            TimeSpaceDll.CAL2UTC(out GlobalEndTime, 1);
            TimeSpaceDll.CAL2UTC(out GlobalCurrentTime, 1);
            CurrentTime = GlobalCurrentTime;

            CurrentStepIndex = 0;
            if (GlobalEndTime.Jd > GlobalStartTime.Jd)
            {
                base.Init();

                //string str1= DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff");

                string str2 = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff");
                SegmentColletion[0].Init();
                string str3 = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff");
                SegmentColletion[1].Init(); //环境段初始化（模型初始化），不能屏蔽，与预初始化PreInit（读文件）功能不同。
                string str4 = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff");
                SegmentColletion[2].Init();
                string str5 = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff");
                SegmentColletion[3].Init();
                string str6 = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff");

                Status = ESimStatus.Inited;

                DlgReportSimInfo(SimInfo.NewSimInfo(this.Name, "初始化已完成!", OutputType.消息, CurrentTime));
                MainDispatcher.MainWindowDispatcher.BeginInvoke(new Action(() =>
                {
                    MessageBox.Show("初始化结束!");
                }));
            }
            else
            {
                MainDispatcher.MainWindowDispatcher.Invoke(new Action(() => { MessageBox.Show("仿真时间设置有误，请检查后重试!"); }));
                Status = ESimStatus.UnInited;
            }
        }

        public void Run()
        {
            SegmentColletion[1].Init();//由于观测数据在初始化时提前计算了，导致读电离层文件的时间已到结束时间；如果观测数据不在初始化时预计算，该句可删除
            Status = ESimStatus.Run;
            UpdateSimTime();
            stepRunTimer.IsEnabled = true;
        }

        public void Pause()
        {
            Status = ESimStatus.Pause;
            stepRunTimer.IsEnabled = false;
        }

        public void Continue()
        {
            Status = ESimStatus.Run;
            stepRunTimer.IsEnabled = true;
        }

        public void RunSlower()
        {
            string msg = "";
            OutputType type = OutputType.消息;
            if (RunSpeed*2 < 1)
            {
                RunSpeed = RunSpeed * 2;
                stepRunTimer.Interval = TimeSpan.FromSeconds(RunSpeed);
                msg = "减速运行，当前速度为：每" + RunSpeed + "s执行一步计算";
            }
            else
            {
                msg = "当前速度已达限值，无法再减速!";
                type = OutputType.警告;
            }
            DlgReportSimInfo(SimInfo.NewSimInfo(this.Name, msg, type, CurrentTime));
        }

        public void RunFaster()
        {
            string msg = "";
            OutputType type = OutputType.消息;
            if (RunSpeed/2 >0.05)
            {
                RunSpeed = RunSpeed / 2;
                stepRunTimer.Interval = TimeSpan.FromSeconds(RunSpeed);
                msg = "加速运行，当前速度为：每" + RunSpeed + "s执行一步计算";
            }
            else
            {
                msg = "当前速度已达限值，无法再加速!";
                type = OutputType.警告;
            }
            DlgReportSimInfo(SimInfo.NewSimInfo(this.Name, msg, type, CurrentTime));
        }

        public void End()
        {
            Status = ESimStatus.End;
            stepRunTimer.Tick -= new EventHandler(stepRunTimer_Tick);
            stepRunTimer.Stop();
        }

        #endregion

        #region 场景时间仿真
        /// <summary>
        /// 仿真场景时间随仿真节拍更新
        /// </summary>
        private void UpdateSimTime()
        {
            double nowTime = CurrentStepIndex * StepSize;
            _CurrentTime.IntJD = GlobalStartTime.IntJD + Math.Floor(nowTime / 86400.0);
            _CurrentTime.DouJD = GlobalStartTime.DouJD + nowTime / 86400.0 - Math.Floor(nowTime / 86400.0);
            _CurrentTime.JD = _CurrentTime.IntJD + _CurrentTime.DouJD;
            if (_CurrentTime.JD <= GlobalEndTime.JD)
            {
                TimeSpaceDll.CAL2UTC(out _CurrentTime, 2);
                if (_CurrentTime.Sec + 0.0001 >= 60)
                {
                    _CurrentTime.sec -= 60;
                    _CurrentTime.min += 1;
                }
                CurrentTime = _CurrentTime;//此处为了把状态栏绑定到当前仿真时间，且必须直接修改属性才能使得数据自动更新
            }
        }


        void GenerateInitTime()
        {
            StartTime = new UTCTimeClass(2015, 10, 1, 12, 0, 0.0, 0.0);
            EndTime = new UTCTimeClass(2015, 10, 1, 13, 0, 0.0, 0.0);
            EpochTime = new UTCTimeClass(2015, 10, 1, 12, 0, 0.0, 0.0);
            CurrentTime = StartTime.ToUTCTime();
        }
        #endregion

        #region 单步运行
        void stepRunTimer_Tick(object sender, EventArgs e)
        {
            if (CurrentTime.Jd <= GlobalEndTime.Jd)
            {
                //执行各仿真段单步运行
                StepRun();

                //仿真时间往前推一个节拍
                CurrentStepIndex++;

                UpdateSimTime();

                if (stkPluginList.Count > 0)
                {
                    stkPluginList[0].UpdateStkTime(GlobalCurrentTime.ToDateTime(), GlobalStepSize);
                }
            }
            else
            {
                //仿真时间往前推一个节拍
                CurrentStepIndex = 0;

                if (RunMode == ERunMode.END)
                {
                    stepRunTimer.Stop();
                    Status = ESimStatus.Inited;
                    MessageBox.Show("运行结束!");
                }
                else
                {
                    ObsSaveFlag = false;
                    UpdateSimTime();
                    if (stkPluginList.Count > 0)
                    {
                        stkPluginList[0].UpdateStkTime(GlobalCurrentTime.ToDateTime(), GlobalStepSize);
                        stkPluginList[0].STKStart();
                    }
                }
            }
        }

        public override void StepRun()
        {
            base.StepRun();
            foreach (var item in SegmentColletion)
            {
                item.StepRun();
            }
            DlgEarthMapUpdate();
        }
        #endregion

        #region 环境段初始化
        /// <summary>
        /// 初始化环境段模型
        /// </summary>
        void EnvironmentSegmentList_Add()
        {
            /// <summary>
            /// 环境段树形列表
            /// </summary>
            (SegmentColletion[1] as EnvironmentSegment).EnvModelList.Add(new SpaceEnvModel() { Name = "空间环境", Type = EnvModelType.SpaceEnv });
            (SegmentColletion[1] as EnvironmentSegment).EnvModelList.Add(new AstronomyEnvModel() { Name = "天文环境", Type = EnvModelType.AstronomyEnv });
            (SegmentColletion[1] as EnvironmentSegment).EnvModelList.Add(new GeographyEnvModel() { Name = "地理环境", Type = EnvModelType.GeographyEnv });
            EnvironmentSegment environmentSegment = (EnvironmentSegment)(SegmentColletion[1]);            
            (environmentSegment.EnvModelList[0] as SpaceEnvModel).SpaceEnvModelList.Add(new IonTECSimModel() { Name = "电离层环境", Type = EnvModelType.IonTECSim });
            (environmentSegment.EnvModelList[0] as SpaceEnvModel).SpaceEnvModelList.Add(new ClimateSimModel() { Name = "气象环境", Type = EnvModelType.ClimateSim }); 
            (environmentSegment.EnvModelList[1] as AstronomyEnvModel).AstronomyEnvModelList.Add(new AstroMotionModel() { Name = "天体运动", Type = EnvModelType.AstroMotion });
            (environmentSegment.EnvModelList[1] as AstronomyEnvModel).AstronomyEnvModelList.Add(new EarthAutoTurnModel() { Name = "地球自转", Type = EnvModelType.EarthAutoTurn });
        }

        /// <summary>
        /// 初始化环境段数据
        /// </summary>
        public void EnvironmentSegmentInit()
        {
            if (IsStarted)
            {
                (SegmentColletion[1] as EnvironmentSegment).PreInit();
            }
        }
        #endregion

        #region 任务执行计数方法

        /// <summary>
        /// 每执行一次增加一个已完成任务量
        /// </summary>
        void AddExecuteMission()
        {
            CompletedMissionNum++;
            PercentValue = CompletedMissionNum / TotalMissionNum * 100;
        }

        void CalculateTotalMission()
        {
            ClearMissionData();
            TotalMissionNum += (SegmentColletion[0] as SpaceSegment).AllSatellite.Count;
            foreach (var subGround in (SegmentColletion[2] as GroundSegment).SubGroundSegmentList)
            {
                foreach (var ground in subGround.GroundList)
                {
                    TotalMissionNum += ground.StationList.Count;
                }
            }
            TotalMissionNum += (SegmentColletion[3] as UserSegment).UserModelList.Count;
            foreach (var user in (SegmentColletion[3] as UserSegment).UserModelList)
            {
                TotalMissionNum += user.RecCollection.Count;
            }
        }

        /// <summary>
        /// 清除任务执行进度控制数据
        /// </summary>
        public void ClearMissionData()
        {
            TotalMissionNum = 0;
            CompletedMissionNum = 0;
            PercentValue = 0;
        }
        #endregion

    }

    public enum PlayScenarioType
    {
        CreateNew,     //  表示新建场景
        Navigation,
        ShenZhou,
        AMM,
        UAV,
        LaunchVehicle
    }
}
